/*****************************************************************************
* FILE PURPOSE: This file implements PHY TX testbench
*******************************************************************************
*
* FILE NAME: test_tx.c
*
* DESCRIPTION:
*       This file contains functions used for receive state machine.
*
*  Copyright (c) 2009 Texas Instruments Inc.
*  All Rights Reserved This program is the confidential and proprietary
*  product of Texas Instruments Inc.  Any Unauthorized use, reproduction or
*  transfer of this program is strictly prohibited.
*
* HISTORY:
*
* 04/20/2009 fum    Written
*
* LIST OF FUNCTIONS :
*
*
******************************************************************************/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#include "phy.h"
#include "phy_tx.h"
#include "phy_rx.h"

/* Tx Test Mode for diagnostic */
#define PHY_TX_TEST_MODE_ON           0x0001
#define PHY_TX_TEST_MCS_SWEEP         0x0002
#define PHY_TX_TEST_PPDU_LEN_SWEEP    0x0004
#define PHY_TX_TEST_PKT               0x0008
#define PHY_TX_TEST_CONT              0x0010

#define PHY_TX_TEST_ALL_SWEEP         (PHY_TX_TEST_MCS_SWEEP | PHY_TX_TEST_PPDU_LEN_SWEEP)


/* Test step thru predetermined PPDU lengths */
#define PHY_TX_TEST_PPDU_LEN_STEP            0    // Step thru PPDU lengths
#define PHY_TX_TEST_NUM_PPDU_STEPS           3    // 3 lens only

/* Test Sweep all MCS */
#define PHY_TX_TEST_DEFAULT_MCS_SWEEP        0x0  // sweep = 0x2, no sweep = 0 

/* Test Sweep all ppdu payload len */
#define PHY_TX_TEST_DEFAULT_PPDU_LEN_SWEEP   0x0  // sweep = 0x4, no sweep = 0              

/* Number of packets per setting */
#define PHY_TX_TEST_DEFAULT_NUM_PPDU        10

/* Default phy cfg */
#define PHY_TX_TEST_DEFAULT_PPDU_LEN		40
#define PHY_TX_TEST_DEFAULT_LEVEL			2                   // max -6 dB 
#define PHY_TX_TEST_DEFAULT_MOD             0   // DQPSK
#define PHY_TX_TEST_DEFAULT_FEC             1   // fec
#define PHY_TX_TEST_DEFAULT_PPDU_TIME       2240   // immediate start

/* Defines */
#define PHY_TX_TEST_PPDU_LENGTH				378 
#define PHY_TX_TEST_BUF_SIZE				378 
#define PHY_TX_TEST_HDR_SIZE				4  //16*4=64bits enought for MAC_H (54)

/* Define data buffers */
int16 hdrBuf[PHY_TX_TEST_HDR_SIZE];
int16 ppduBuf[PHY_TX_TEST_BUF_SIZE];
PHY_tx_ppdu_t PHY_tx_ppdu_s;

SINT16 test_ppducnt = 0;
SINT16 ppduStepCnt = 0;

/* Test mode set up */
PHY_txTestMode_t PHY_txTest_s =
{
	0,//(PHY_TX_TEST_MODE_ON | PHY_TX_TEST_DEFAULT_MCS_SWEEP | PHY_TX_TEST_DEFAULT_PPDU_LEN_SWEEP),
	5, //377,//PHY_TX_TEST_DEFAULT_PPDU_LEN,
	173, //PHY_TX_TEST_DEFAULT_PPDU_TIME,
	PHY_TX_TEST_DEFAULT_NUM_PPDU,
	0,//PHY_TX_TEST_DEFAULT_MOD,
	1, //PHY_TX_TEST_DEFAULT_FEC,
	2, //PHY_TX_TEST_DEFAULT_LEVEL,
	2, //data pattern 2-ramp; 3-cert
	0
};

UINT16 maxPpduLen[8] =
{
	756,  // uncoded DBPSK, 63*96/8=756
	1512, // uncoded DQPSK, 63*96*2/8=1512
	2268, // uncoded D8PSK, 63*96*3/8=2268
	0,    // reserved
	377,  // coded DBPSK, 63*96/8/2-1=377
	755,  // coded DQPSK, 63*96*2/8/2-1=755
	1133, // coded D8PSK, 63*96*3/8/2-1=1133
	92    // robo
};

UINT16 stepPpduLen[7][PHY_TX_TEST_NUM_PPDU_STEPS] =
{
	{ 1/*252*/,  504,  756 },  
	{ 1/*504*/, 1008, 1512 }, 
	{ 1/*756*/, 1512, 2268 }, 
	{   0,    0,    0 },    
	{ 1/*100*/,  200,  377 },  
	{ 1/*200*/,  400,  755 },  
	{ 1/*350*/,  750, 1133 }
};

/***********************************************************************/
/* PHY TX callback                                                     */
/***********************************************************************/
Uint16 cb_ev=0;

void cb_tx(PHY_ev_t eventID, PHY_cbData_t *data_p)
{
	cb_ev = eventID;

	test_ppducnt++;
}

/***********************************************************************/
/* Main function                                                       */
/***********************************************************************/
UINT16 test_robo = 0;

void main(void)
{
	Uint16 idx, i, maxLen;
	Uint16 *buf_p = (Uint16 *)ppduBuf;
	PHY_txGetData_t getData;
	Uint16 idx1 = 0, idx2 = 1;
	HAL_afe_prfParms_t afePrfParms;

	/* HAL profile (tx/rx sampling and PWM frequencies */
	afePrfParms.rx_fs_kHz = 250;
	afePrfParms.tx_fs_kHz = 250;
	afePrfParms.tx_pwm_kHz = 1000;

	HAL_afeInit(&afePrfParms);

	PHY_txInit();

	PHY_rxInit();

	PHY_tx_ppdu_s.length = PHY_txTest_s.ppduLength;
	PHY_tx_ppdu_s.level  = PHY_txTest_s.txLevel;
	PHY_tx_ppdu_s.mcs    = PHY_txTest_s.mod + (PHY_txTest_s.fec << 2);
	PHY_tx_ppdu_s.txTime = 0; 

	PHY_tx_ppdu_s.ppduHdr_p = (Uint16 *)&hdrBuf[0];
	PHY_tx_ppdu_s.ppduPld_p = (Uint16 *)&ppduBuf[0];

	/* Fill the ppduBuf with ramp data*/
	for (idx = 0; idx < (PHY_TX_TEST_BUF_SIZE); idx++)
	{
		*buf_p++ = ((((idx & 127) << 1) + 1) << 8) | ((idx & 127) << 1);
	}

	buf_p = (Uint16 *)hdrBuf;
	for (i = 0; i < PHY_TX_TEST_HDR_SIZE; i++)
	{
		*buf_p++ = ((((i & 127) << 1) + 1) << 8) | ((i & 127) << 1);
	}

	/* set PRIM/ROBO mode */
	PHY_txSet(PHY_TX_SETMODE, (PHY_txSetData_t *)&test_robo);
	PHY_rxSet(PHY_RX_SET_ROBOMODE, (PHY_rxSetData_t *)&test_robo);

	/* Start TX for the first time */
	PHY_txPpdu(&PHY_tx_ppdu_s, cb_tx);

	/* Infinite loop */
	while(1)
	{
		/* State transition */
		PHY_txSmRun();

		/* Check if PPDU is done */
		if (cb_ev == PHY_EV_TX_PPDU_DONE)
		{
			if (test_ppducnt >= PHY_txTest_s.numPpdu)
			{
				/* sweep mcs only */
				if ((PHY_txTest_s.flags & PHY_TX_TEST_ALL_SWEEP) == PHY_TX_TEST_MCS_SWEEP)
				{
					/* next mcs */
					if (PHY_tx_ppdu_s.mcs == PRIME_PRCL_D8PSK_F)
					{
						PHY_tx_ppdu_s.mcs = PRIME_PRCL_DBPSK;
					}
					else if (PHY_tx_ppdu_s.mcs == PRIME_PRCL_D8PSK)
					{
						PHY_tx_ppdu_s.mcs = PRIME_PRCL_DBPSK_F;
					}
					else
					{
						PHY_tx_ppdu_s.mcs++;
					}

					/* Limit the ppdu len when mcs changes */
					maxLen = maxPpduLen[PHY_tx_ppdu_s.mcs];

					if (PHY_tx_ppdu_s.length >= maxLen)
					{
						PHY_tx_ppdu_s.length = maxLen-1;
					}
				}
				else if ((PHY_txTest_s.flags & PHY_TX_TEST_PPDU_LEN_SWEEP) == PHY_TX_TEST_PPDU_LEN_SWEEP)
				{
					/* next ppdu length */
					PHY_tx_ppdu_s.length++;

					maxLen = maxPpduLen[PHY_tx_ppdu_s.mcs];

					if (PHY_tx_ppdu_s.length >= maxLen)
					{
						if ((PHY_txTest_s.flags & PHY_TX_TEST_PPDU_LEN_SWEEP) == PHY_TX_TEST_PPDU_LEN_SWEEP)
						{
							PHY_tx_ppdu_s.length = 1;
						}
						else
						{
							PHY_tx_ppdu_s.length = stepPpduLen[PHY_tx_ppdu_s.mcs][0];

							ppduStepCnt = 0; 
						}

						/* sweep mcs too */
						if ((PHY_txTest_s.flags & PHY_TX_TEST_MCS_SWEEP) == PHY_TX_TEST_MCS_SWEEP)
						{
							/* next mcs */
							if (PHY_tx_ppdu_s.mcs == PRIME_PRCL_D8PSK_F)
							{
								PHY_tx_ppdu_s.mcs = PRIME_PRCL_DBPSK;
							}
							else if (PHY_tx_ppdu_s.mcs == PRIME_PRCL_D8PSK)
							{
								PHY_tx_ppdu_s.mcs = PRIME_PRCL_DBPSK_F;
							}
							else
							{
								PHY_tx_ppdu_s.mcs++;
							}
						}
					}
				}

				/* reset */
				test_ppducnt = 0;
			}

			// ROBO sweep len
			if (PHY_tx_ppdu_s.length > PHY_ppduMaxLen[PHY_tx_ppdu_s.mcs])
			{
				PHY_tx_ppdu_s.length = 1;
			}

			/* Start the next PPDU */
			PHY_txPpdu(&PHY_tx_ppdu_s, cb_tx);
      
			cb_ev = 0;
		}

		if (cb_ev == PHY_EV_TX_TESTMODE_DONE)
		{
			cb_ev = 0;

			PHY_txPpdu(&PHY_tx_ppdu_s, cb_tx);
		}
	 } // while(1)
}

